<?php
/**
 * Description: 设置考试项目
 * User: devforma
 * Date: 15/4/3
 * Time: 18:27
 */

require __DIR__ . '/includes/utils.php';
class SetExam implements iController {

    private $specialNoteExams, $specialNoteIds, $specialHerarchyExams, $GJExamId, $noteHierarchy;

    function __construct() {
        $this->specialNoteExams = array(
            113 => '浙江',
            128 => '江苏',
            123 => '广东',
            1177 => '深圳',
            58 => '吉林',
            116 => '河北',
            129 => '天津'
        );

        $this->noteHierarchy = getNewNoteHierarchy();

        //获取数字推理下面的叶子知识点
        $this->getSpecialNoteIds(1453);

        $this->specialHerarchyExams = array(
            115 => '内蒙古',
            889 => '青海',
            1087 => '甘肃',
            1177 => '深圳市考',
            1234 => '广州市考',
            902 => '政法干警'
        );

        $this->GJExamId = 1126; //国考考试项目的id

    }

    /**
     * api请求处理主函数
     * @param array $queryArgs 就是$_REQUEST变量
     * @return array api返回结果，必须含response_code
     */
    public function output($queryArgs) {
        global $cmsdb;
        
        if (validateUser($queryArgs) !== 1)
            return genOutput(1000);

        //用户校验
        $userId = $queryArgs['user_id'];

        if (empty($queryArgs['exam_id'])) {
            return genOutput(1000);
        }

        $dataExists = $cmsdb->getRow('SELECT * FROM `qb_user_data` WHERE `user_id`=:user_id',
            array(':user_id' => $userId));

        //选过考试项目，且重新选择该考试项目
        if (!empty($dataExists) && $dataExists->exam_detail_id == $queryArgs['exam_id']) {
            return genOutput(1, array('sno' => intval($dataExists->user_sno)));
        }

        /**
         * 对内蒙古，青海，甘肃三个省份，采用国考的知识点体系
         * updated: 2015-05-20
         */
        if (isset($this->specialHerarchyExams[$queryArgs['exam_id']]))
            $examId = $this->GJExamId;
        else
            $examId = $queryArgs['exam_id'];

        //获取指定考试项目下的知识点信息
        $sql = "SELECT nq.* FROM `{$cmsdb->noteQuality}` AS nq " .
            "JOIN `{$cmsdb->examDetail}` AS e ON nq.testarea_id=e.exam_id " .
            'AND e.id=:exam_id AND nq.note_id != 0 AND nq.available=1 ' .
            'ORDER BY nq.rate DESC';
        $notes = $cmsdb->getResults($sql, array(':exam_id' => $examId));

        $noteInfoArray = array();
        if (!empty($dataExists)) { //已选过，需进行知识点的合并
            $userSno = $dataExists->user_sno;

            $noteBefore = normalizeUserNoteInfo($dataExists->note_info);

            $newNotes = []; //需要重新计算知识点掌握情况的知识点列表
            foreach ($notes as $note) {

                /**
                 * 除去浙江，江苏，广东，广州，深圳，吉林，河北，天津之外，所有考试项目，屏蔽“数字推理”知识点组下面的知识点
                 * updated: 2015-05-20
                 */
                if (!isset($this->specialNoteExams[$queryArgs['exam_id']]) && in_array($note->note_id, $this->specialNoteIds))
                    continue;


                if (!isset($noteBefore[$note->note_id])) {
                    $newNotes[] = $note->note_id;
                    $noteInfoArray[$note->note_id] = array(
                        1, //分值,value
                        0, //做对题目数,rightCount
                        0, //总题目数,totalCount
                        0, //掌握级别,level
                        0, //当前的推荐知识点标记,recomend 同一时间只有一个知识点该值为1
                    );

                } else {
                    $nb = array_values($noteBefore[$note->note_id]); //更新为数字索引
                    $nb[4] = 0; //重置知识点推荐状态
                    $noteInfoArray[$note->note_id] = $nb;
                }
            }

            //2016-08-11 新知识点的统计计算
            if (!empty($newNotes)) {
                $newNoteSummary = $this->getNewNoteSummary($userId, $examId, $newNotes);

                foreach ($newNoteSummary as $noteId => $note) {
                    $noteInfoArray[$noteId] = $note;
                }
            }

            $noteInfoArray[key($noteInfoArray)][4] = 1; //第一个知识点为推荐知识点
            
            $score = calEvaluationScore($noteInfoArray, $examId);

            //更新估分排名缓存
            updateScoreRank($queryArgs['exam_id'], $dataExists->score, $score);

            $new = array(
                'note_info' => json_encode($noteInfoArray),
                'score' => $score,
                'exam_detail_id' => $queryArgs['exam_id']
            );

            //删除cache
            $cacheKey = 'qb_userData:'.$userId;
            cacheDelete($cacheKey);

            $result = $cmsdb->update('qb_user_data', $new, array('user_id' => $userId));

        } else { //第一次选
            $userSno = $this->getSno($userId);

            foreach ($notes as $index => $note) {
                /**
                 * 除去浙江，江苏，广东，广州，深圳，吉林，河北，天津之外，所有考试项目，屏蔽“数字推理”知识点组下面的知识点
                 * updated: 2015-05-20
                 */
                if (!isset($this->specialNoteExams[$queryArgs['exam_id']]) && in_array($note->note_id, $this->specialNoteIds))
                    continue;

                $noteInfoArray[$note->note_id] = array(
                    1, //分值,value
                    0, //做对题目数,rightCount
                    0, //总题目数,totalCount
                    0, //掌握级别,level
                    $index == 0 ? 1 : 0  //当前的推荐知识点标记,同一时间只有一个知识点该值为1,默认第一个知识点为1
                );
            }

            $score = calEvaluationScore($noteInfoArray, $examId);

            //更新估分排名缓存
            updateScoreRank($queryArgs['exam_id'], 0, $score);

            $new = array(
                'user_id' => $userId,
                'note_info' => json_encode($noteInfoArray),
                'summary_info' => serialize(array(
                    0, //总时长(秒),total_time
                    array(), //历史预估分,history_score
                    0 //正确题目总数,right_count
                )),
                'user_sno' => $userSno,
                'score' => $score,
                'exam_detail_id' => $queryArgs['exam_id'],
                'create_time' => date('Y-m-d H:i:s'),
                'question_count' => 0,
                'accuracy' => 0.0
            );

            $result = $cmsdb->insert('qb_user_data', $new);
        }

        if (!empty($result)) {
            return genOutput(1, array('sno' => intval($userSno)));
        } else {
            return genOutput(1000);
        }
    }

    /**
     * 根据历史答题数据获取知识点统计信息
     *
     * @param int $userId 用户id
     * @param int $examId 考试项目id
     * @param array $newNotes 新知识点
     * @return array
     */
    private function getNewNoteSummary($userId, $examId, $newNotes) {
        global $uddb;

        $str = implode(',', $newNotes);

        $table = $uddb->table($uddb->qbUserTests)->sublist($userId);
        $data = (array)$uddb->getResults("SELECT `note_id`, `is_right` FROM `{$table}` WHERE `user_id`={$userId} AND `note_id` IN ({$str}) ORDER BY `id` DESC ");

        //获取每个知识点的目标正确率
        if ($results = getNotesByTestId($examId)) {
            foreach ($results as $rs) {
                $notesAccuracy[$rs->note_id] = $rs->target_accuracy;
            }
        } else {
            $notesAccuracy = [];
        }

        $notes = [];
        //根据已做题目信息,统计知识点信息
        foreach ($data as $item) {
            if (!isset($notes[$item->note_id])) {
                $notes[$item->note_id] = [
                    1, //分值,value
                    0, //做对题目数,rightCount
                    0, //总题目数,totalCount
                    0, //掌握级别,level
                    0  //当前的推荐知识点标记
                ];
            }

            $notes[$item->note_id][2]++; //总题目数

            if ($item->is_right) {
                $notes[$item->note_id][1]++; //做对题目数
            }
        }

        //计算知识点掌握情况
        foreach ($notes as $noteId => &$note) {
            if ($note[2] < 30) {
                $note[3] = 1;
            } else {
                $currAccuracy = $note[1] / $note[2];

                $targetAccuracy = isset($notesAccuracy[$noteId]) ? $notesAccuracy[$noteId] : 1;
                if ($currAccuracy < $targetAccuracy) { //未达到目标正确率
                    $note[3] = round(4*($currAccuracy-$targetAccuracy)/$targetAccuracy) + 5;
                } else {
                    $note[3] = 5;
                }
            }
        }

        return $notes;
    }


    /**
     * 获取数字推理下面的知识点
     * @param int $noteId
     */
    private function getSpecialNoteIds($noteId) {
        foreach ($this->noteHierarchy as $note) {
            if ($note['parent_id'] != $noteId) continue;

            if ($note['note_type'] == 1) {
                $this->specialNoteIds[] = $note['id'];
            } else {
                $this->getSpecialNoteIds($note['id']);
            }
        }
    }

    /**
     * 生成用户的学号
     * @param int $userId 用户id
     * @return string 学号
     */
    private static function genSno($userId) {
        return substr(strval(time()), -7).substr('00000'.$userId, -3);
    }


    /**
     * 获取用户学号
     * @param int $userId 用户id
     * @return string
     */
    private function getSno($userId) {
        global $uddb;
        $sno = $uddb->getVar('SELECT `user_sno` FROM `user_social_info` WHERE `user_id`='.$userId);

        if (empty($sno)) {
            $sno = self::genSno($userId);

            $uddb->update('user_social_info', array('user_sno' => $sno), array('user_id' => $userId));
        }

        return $sno;
    }
}